package org.gdstash.db.criteria;

import org.gdstash.db.ItemClass;
import org.gdstash.db.SelectionCriteria;
import org.gdstash.util.GDMsgFormatter;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

public class AbstractItemCombination implements CriteriaCombination, Cloneable {
    private String itemClass;
    private String armorClass;
    private String artifactClass;
    private String itemRarity;
    private boolean useArmorClass;
    private boolean useArtifactClass;
    private boolean useItemRarity;
    private boolean useItemName;
    private boolean useSetItem;
    private boolean useBonusSkill;
    private boolean useAllSkills;
    private boolean useMasteryBonusSkills;
    private boolean useSkillModifier;
    private boolean useMasteryModifySkills;
    private boolean useAllItemSkills;
    private boolean useItemSkill;
    private boolean usePrefix;
    private boolean useSuffix;
    private boolean useConversionFrom;
    private boolean useConversionTo;
    private boolean useSlots;
    private boolean petBonus;
    private String itemName;
    private boolean setItem;
    private String bonusSkill;
    private boolean allSkills;
    private boolean masteryBonusSkills;
    private String modifiedSkill;
    private boolean masteryModifySkills;
    private boolean allItemSkills;
    private String itemSkill;
    private String prefixID;
    private String suffixID;
    private int levelMin;
    private int levelMax;
    private int cunningMax;
    private int physiqueMax;
    private int spiritMax;
    public String dmgConversionFrom;
    public String dmgConversionTo;
    private boolean noEnemyOnly;
    private SelectionCriteria criteria;

    public AbstractItemCombination() {
        this.itemClass = null;
        this.armorClass = null;
        this.artifactClass = null;
        this.itemRarity = null;
        this.useArmorClass = false;
        this.useArtifactClass = false;
        this.useItemRarity = false;
        this.useItemName = false;
        this.useSetItem = false;
        this.useBonusSkill = false;
        this.useAllSkills = false;
        this.useMasteryBonusSkills = false;
        this.useSkillModifier = false;
        this.useMasteryModifySkills = false;
        this.useAllItemSkills = false;
        this.useItemSkill = false;
        this.usePrefix = false;
        this.useSuffix = false;
        this.useConversionFrom = false;
        this.useConversionTo = false;
        this.useSlots = false;
        this.petBonus = false;
        this.itemName = null;
        this.setItem = false;
        this.levelMin = -1;
        this.levelMax = -1;
        this.cunningMax = -1;
        this.physiqueMax = -1;
        this.spiritMax = -1;
        this.dmgConversionFrom = null;
        this.dmgConversionTo = null;
        this.noEnemyOnly = true;
        this.criteria = null;
    }

    public AbstractItemCombination(final AbstractItemCombination combo) {
        this.itemClass = combo.itemClass;
        this.armorClass = combo.armorClass;
        this.artifactClass = combo.artifactClass;
        this.itemRarity = combo.itemRarity;
        this.useArmorClass = combo.useArmorClass;
        this.useArtifactClass = combo.useArtifactClass;
        this.useItemRarity = combo.useItemRarity;
        this.useItemName = combo.useItemName;
        this.useSetItem = combo.useSetItem;
        this.useBonusSkill = combo.useBonusSkill;
        this.useAllSkills = combo.useAllSkills;
        this.useMasteryBonusSkills = combo.useMasteryBonusSkills;
        this.useSkillModifier = combo.useSkillModifier;
        this.useMasteryModifySkills = combo.useMasteryModifySkills;
        this.useAllItemSkills = combo.useAllItemSkills;
        this.useItemSkill = combo.useItemSkill;
        this.usePrefix = combo.usePrefix;
        this.useSuffix = combo.useSuffix;
        this.useConversionFrom = combo.useConversionFrom;
        this.useConversionTo = combo.useConversionTo;
        this.useSlots = combo.useSlots;
        this.petBonus = combo.petBonus;
        this.itemName = combo.itemName;
        this.setItem = combo.setItem;
        this.bonusSkill = combo.bonusSkill;
        this.allSkills = combo.allSkills;
        this.masteryBonusSkills = combo.masteryBonusSkills;
        this.modifiedSkill = combo.modifiedSkill;
        this.masteryModifySkills = combo.masteryModifySkills;
        this.allItemSkills = combo.allItemSkills;
        this.itemSkill = combo.itemSkill;
        this.prefixID = combo.prefixID;
        this.suffixID = combo.suffixID;
        this.levelMin = combo.levelMin;
        this.levelMax = combo.levelMax;
        this.cunningMax = combo.cunningMax;
        this.physiqueMax = combo.physiqueMax;
        this.spiritMax = combo.spiritMax;
        this.dmgConversionFrom = combo.dmgConversionFrom;
        this.dmgConversionTo = combo.dmgConversionTo;
        this.noEnemyOnly = combo.noEnemyOnly;
        this.criteria = combo.criteria;
    }

    public AbstractItemCombination(final SelectionCriteria criteria) {
        this();
        this.setItemName(criteria.itemName);
        this.setBonusSkill(criteria.bonusSkill);
        this.setSkillModifier(criteria.modifiedSkill);
        this.setItemSkill(criteria.itemSkill);
        this.setPrefixID(criteria.prefixID);
        this.setSuffixID(criteria.suffixID);
        this.setItem = criteria.setItem;
        this.allSkills = criteria.allSkills;
        this.masteryBonusSkills = criteria.masteryBonusSkills;
        this.allItemSkills = criteria.allItemSkills;
        this.levelMin = criteria.levelMin;
        this.levelMax = criteria.levelMax;
        this.cunningMax = criteria.cunningMax;
        this.physiqueMax = criteria.physiqueMax;
        this.spiritMax = criteria.spiritMax;
        this.dmgConversionFrom = criteria.dmgConversionFrom;
        this.dmgConversionTo = criteria.dmgConversionTo;
        this.noEnemyOnly = criteria.noEnemyOnly;
        this.petBonus = criteria.petBonus;
        this.criteria = criteria;
    }

    @Override
    public AbstractItemCombination clone() {
        final AbstractItemCombination combo = new AbstractItemCombination(this);
        return combo;
    }

    public String getItemClass() {
        return this.itemClass;
    }

    public String getArmorClass() {
        return this.armorClass;
    }

    public String getArtifactClass() {
        return this.artifactClass;
    }

    public String getItemRarity() {
        return this.itemRarity;
    }

    @Override
    public boolean usesArmorClass() {
        return this.useArmorClass;
    }

    @Override
    public boolean usesArtifactClass() {
        return this.useArtifactClass;
    }

    @Override
    public boolean usesItemRarity() {
        return this.useItemRarity;
    }

    @Override
    public boolean usesItemName() {
        return this.useItemName;
    }

    public boolean usesSetItem() {
        return this.useSetItem;
    }

    public boolean usesBonusSkill() {
        return this.useBonusSkill;
    }

    public boolean usesAllSkills() {
        return this.useAllSkills;
    }

    public boolean usesMasteryBonusSkills() {
        return this.useMasteryBonusSkills;
    }

    public boolean usesSkillModifier() {
        return this.useSkillModifier;
    }

    public boolean usesMasteryModifySkills() {
        return this.useMasteryModifySkills;
    }

    public boolean usesAllItemSkills() {
        return this.useAllItemSkills;
    }

    public boolean usesItemSkill() {
        return this.useItemSkill;
    }

    public boolean usesPrefix() {
        return this.usePrefix;
    }

    public boolean usesSuffix() {
        return this.useSuffix;
    }

    public boolean usesConversionFrom() {
        return this.useConversionFrom;
    }

    public boolean usesConversionTo() {
        return this.useConversionTo;
    }

    public boolean usesSlots() {
        return this.useSlots;
    }

    public boolean usesPetBonus() {
        return this.petBonus;
    }

    public String getItemName() {
        return this.itemName;
    }

    public boolean isSetItem() {
        return this.setItem;
    }

    public String getBonusSkillID() {
        return this.bonusSkill;
    }

    public boolean isAllSkills() {
        return this.allSkills;
    }

    public boolean isMasteryBonusSkills() {
        return this.masteryBonusSkills;
    }

    public String getModifiedSkillID() {
        return this.modifiedSkill;
    }

    public boolean isMasteryModifySkills() {
        return this.masteryModifySkills;
    }

    public boolean isAllItemSkills() {
        return this.allItemSkills;
    }

    public String getItemSkillID() {
        return this.itemSkill;
    }

    public String getPrefixID() {
        return this.prefixID;
    }

    public String getSuffixID() {
        return this.suffixID;
    }

    public int getMinLevel() {
        return this.levelMin;
    }

    public int getMaxLevel() {
        return this.levelMax;
    }

    public int getMaxCunning() {
        return this.cunningMax;
    }

    public int getMaxPhysique() {
        return this.physiqueMax;
    }

    public int getMaxSpirit() {
        return this.spiritMax;
    }

    public String getDamageConvertedFrom() {
        return this.dmgConversionFrom;
    }

    public String getDamageConvertedTo() {
        return this.dmgConversionTo;
    }

    public boolean isNoEnemyOnly() {
        return this.noEnemyOnly;
    }

    public List<String> getItemRarities() {
        if (this.criteria == null) {
            return new LinkedList<String>();
        }
        return this.criteria.itemRarity;
    }

    public List<String> getArmorClasses() {
        if (this.criteria == null) {
            return new LinkedList<String>();
        }
        return this.criteria.armorClass;
    }

    public List<String> getArtifactClasses() {
        if (this.criteria == null) {
            return new LinkedList<String>();
        }
        return this.criteria.artifactClass;
    }

    private void init() {
        this.useArmorClass = false;
        if (!this.criteria.armorClass.isEmpty() && this.isArmor()) {
            this.useArmorClass = true;
        }
        this.useArtifactClass = false;
        if (!this.criteria.artifactClass.isEmpty() && this.isArtifact()) {
            this.useArtifactClass = true;
        }
        this.useItemRarity = false;
        if (!this.criteria.itemRarity.isEmpty() && ItemClass.hasRarity(this.itemClass)) {
            this.useItemRarity = true;
        }
        this.useItemName = false;
        if (this.criteria.itemName != null && !this.criteria.itemName.isEmpty()) {
            this.useItemName = true;
        }
        this.useSetItem = this.criteria.setItem;
        this.useBonusSkill = false;
        if (this.criteria.bonusSkill != null && !this.criteria.bonusSkill.isEmpty() && !this.criteria.masteryBonusSkills) {
            this.useBonusSkill = true;
        }
        this.useAllSkills = this.criteria.allSkills;
        this.useMasteryBonusSkills = this.criteria.masteryBonusSkills;
        this.useSkillModifier = false;
        if (this.criteria.modifiedSkill != null && !this.criteria.modifiedSkill.isEmpty() && !this.criteria.masteryModifySkills) {
            this.useSkillModifier = true;
        }
        this.useMasteryModifySkills = this.criteria.masteryModifySkills;
        this.useAllItemSkills = this.criteria.allItemSkills;
        this.useItemSkill = false;
        if (this.criteria.itemSkill != null && !this.criteria.itemSkill.isEmpty()) {
            this.useItemSkill = true;
        }
        this.usePrefix = false;
        if (this.criteria.prefixID != null && !this.criteria.prefixID.isEmpty()) {
            this.usePrefix = true;
        }
        this.useSuffix = false;
        if (this.criteria.suffixID != null && !this.criteria.suffixID.isEmpty()) {
            this.useSuffix = true;
        }
        this.useConversionFrom = false;
        if (this.criteria.dmgConversionFrom != null && !this.criteria.dmgConversionFrom.isEmpty()) {
            this.useConversionFrom = true;
        }
        this.useConversionTo = false;
        if (this.criteria.dmgConversionTo != null && !this.criteria.dmgConversionTo.isEmpty()) {
            this.useConversionTo = true;
        }
        this.useSlots = false;
        if (this.hasSlots()) {
            this.useSlots = true;
        }
    }

    private boolean isArmor() {
        return this.itemClass != null && (this.itemClass.equals("ArmorProtective_Head") || this.itemClass.equals("ArmorProtective_Shoulders") || this.itemClass.equals("ArmorProtective_Chest") || this.itemClass.equals("ArmorProtective_Hands") || this.itemClass.equals("ArmorProtective_Legs") || this.itemClass.equals("ArmorProtective_Feet"));
    }

    private boolean isArtifact() {
        return this.itemClass != null && this.itemClass.equals("ItemArtifact");
    }

    private boolean hasSlots() {
        return this.itemClass != null && (this.itemClass.equals("ItemRelic") || this.itemClass.equals("ItemEnchantment"));
    }

    public static List<String> wrapString(final ResultSet rs, final int pos) throws SQLException {
        final LinkedList<String> list = new LinkedList<String>();
        final String executedQuery = rs.getStatement().toString();
        while (rs.next()) {
            final String s = rs.getString(pos);
            if (s != null && !s.isEmpty()) {
                list.add(s);
            }
        }
        return list;
    }

    public static List<Integer> wrapInteger(final ResultSet rs, final int pos) throws SQLException {
        final LinkedList<Integer> list = new LinkedList<Integer>();
        while (rs.next()) {
            final int i = rs.getInt(pos);
            final Integer iI = i;
            list.add(iI);
        }
        return list;
    }

    public static void mergeIntList(final List<Integer> listAll, final List<Integer> list) {
        for (final Integer i : list) {
            if (!listAll.contains(i)) {
                listAll.add(i);
            }
        }
    }

    public static void mergeStringList(final List<String> listAll, final List<String> list) {
        for (final String s : list) {
            if (!listAll.contains(s)) {
                listAll.add(s);
            }
        }
    }

    public String determineSlotConditions(final String prefix) {
        String command = "";
        if (!this.useSlots) {
            return command;
        }
        boolean firstSlot = true;
        if (this.criteria.slotAxe1H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_AXE_1H = true";
            } else {
                command = command + prefix + "SLOT_AXE_1H = true";
            }
        }
        if (this.criteria.slotAxe2H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_AXE_2H = true";
            } else {
                command = command + prefix + "SLOT_AXE_2H = true";
            }
        }
        if (this.criteria.slotDagger1H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_DAGGER_1H = true";
            } else {
                command = command + prefix + "SLOT_DAGGER_1H = true";
            }
        }
        if (this.criteria.slotMace1H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_MACE_1H = true";
            } else {
                command = command + prefix + "SLOT_MACE_1H = true";
            }
        }
        if (this.criteria.slotMace2H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_MACE_2H = true";
            } else {
                command = command + prefix + "SLOT_MACE_2H = true";
            }
        }
        if (this.criteria.slotScepter1H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_SCEPTER_1H = true";
            } else {
                command = command + prefix + "SLOT_SCEPTER_1H = true";
            }
        }
        if (this.criteria.slotSpear1H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_SPEAR_1H = true";
            } else {
                command = command + prefix + "SLOT_SPEAR_1H = true";
            }
        }
        if (this.criteria.slotSpear2H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_SPEAR_2H = true";
            } else {
                command = command + prefix + "SLOT_SPEAR_2H = true";
            }
        }
        if (this.criteria.slotStaff2H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_STAFF_2H = true";
            } else {
                command = command + prefix + "SLOT_STAFF_2H = true";
            }
        }
        if (this.criteria.slotSword1H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_SWORD_1H = true";
            } else {
                command = command + prefix + "SLOT_SWORD_1H = true";
            }
        }
        if (this.criteria.slotSword2H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_SWORD_2H = true";
            } else {
                command = command + prefix + "SLOT_SWORD_2H = true";
            }
        }
        if (this.criteria.slotRanged1H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_RANGED_1H = true";
            } else {
                command = command + prefix + "SLOT_RANGED_1H = true";
            }
        }
        if (this.criteria.slotRanged2H) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_RANGED_2H = true";
            } else {
                command = command + prefix + "SLOT_RANGED_2H = true";
            }
        }
        if (this.criteria.slotShield) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_SHIELD = true";
            } else {
                command = command + prefix + "SLOT_SHIELD = true";
            }
        }
        if (this.criteria.slotOffhand) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_OFFHAND = true";
            } else {
                command = command + prefix + "SLOT_OFFHAND = true";
            }
        }
        if (this.criteria.slotAmulet) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_AMULET = true";
            } else {
                command = command + prefix + "SLOT_AMULET = true";
            }
        }
        if (this.criteria.slotBelt) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_BELT = true";
            } else {
                command = command + prefix + "SLOT_BELT = true";
            }
        }
        if (this.criteria.slotMedal) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_MEDAL = true";
            } else {
                command = command + prefix + "SLOT_MEDAL = true";
            }
        }
        if (this.criteria.slotRing) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_RING = true";
            } else {
                command = command + prefix + "SLOT_RING = true";
            }
        }
        if (this.criteria.slotHead) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_HEAD = true";
            } else {
                command = command + prefix + "SLOT_HEAD = true";
            }
        }
        if (this.criteria.slotShoulders) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_SHOULDERS = true";
            } else {
                command = command + prefix + "SLOT_SHOULDERS = true";
            }
        }
        if (this.criteria.slotChest) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_CHEST = true";
            } else {
                command = command + prefix + "SLOT_CHEST = true";
            }
        }
        if (this.criteria.slotHands) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_HANDS = true";
            } else {
                command = command + prefix + "SLOT_HANDS = true";
            }
        }
        if (this.criteria.slotLegs) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_LEGS = true";
            } else {
                command = command + prefix + "SLOT_LEGS = true";
            }
        }
        if (this.criteria.slotFeet) {
            if (firstSlot) {
                firstSlot = false;
                command += " AND ( ";
            } else {
                command += " OR ";
            }
            if (prefix == null) {
                command += "SLOT_FEET = true";
            } else {
                command = command + prefix + "SLOT_FEET = true";
            }
        }
        if (!firstSlot) {
            command += " )";
        }
        return command;
    }

    @Override
    public void setItemClass(final String itemClass) {
        this.itemClass = itemClass;
        if (itemClass != null && itemClass.isEmpty()) {
            this.itemClass = null;
        }
        this.init();
    }

    @Override
    public void setArmorClass(final String armorClass) {
        this.armorClass = armorClass;
        if (armorClass != null && armorClass.isEmpty()) {
            this.armorClass = null;
        }
    }

    @Override
    public void setArtifactClass(final String artifactClass) {
        this.artifactClass = artifactClass;
        if (artifactClass != null && artifactClass.isEmpty()) {
            this.artifactClass = null;
        }
    }

    public void setBonusSkill(final String bonusSkill) {
        this.bonusSkill = bonusSkill;
        if (bonusSkill != null && bonusSkill.isEmpty()) {
            this.bonusSkill = null;
        }
    }

    public void setSkillModifier(final String modifiedSkill) {
        this.modifiedSkill = modifiedSkill;
        if (modifiedSkill != null && modifiedSkill.isEmpty()) {
            this.modifiedSkill = null;
        }
    }

    public void setItemSkill(final String itemSkill) {
        this.itemSkill = itemSkill;
        if (itemSkill != null && itemSkill.isEmpty()) {
            this.itemSkill = null;
        }
    }

    @Override
    public void setItemRarity(final String itemRarity) {
        this.itemRarity = itemRarity;
        if (itemRarity != null && itemRarity.isEmpty()) {
            this.itemRarity = null;
        }
    }

    @Override
    public void setItemName(final String itemName) {
        this.itemName = itemName;
        if (itemName != null && itemName.isEmpty()) {
            this.itemName = null;
        }
    }

    @Override
    public SelectionCriteria getCriteria() {
        return this.criteria;
    }

    public void setPrefixID(final String prefixID) {
        this.prefixID = prefixID;
        if (prefixID != null && prefixID.isEmpty()) {
            this.prefixID = null;
        }
    }

    @Override
    public List<CriteriaCombination> createLevel1Combinations(final CriteriaCombination cc) {
        final CriteriaCombination combo = cc.clone();
        final List<CriteriaCombination> list = new LinkedList<CriteriaCombination>();
        for (final String itemClass : this.getCriteria().itemClass) {
            combo.setItemClass(itemClass);
            boolean found = false;
            if (combo.usesItemRarity()) {
                for (final String itemRarity : this.getItemRarities()) {
                    combo.setItemRarity(itemRarity);
                    if (combo.usesArmorClass()) {
                        for (final String armorClass : this.getArmorClasses()) {
                            combo.setArmorClass(armorClass);
                            list.add(combo.clone());
                        }
                        found = true;
                    }
                    if (!found) {
                        list.add(combo.clone());
                    }
                }
            } else {
                if (combo.usesArmorClass()) {
                    for (final String armorClass2 : this.getArmorClasses()) {
                        combo.setArmorClass(armorClass2);
                        list.add(combo.clone());
                    }
                    found = true;
                }
                if (combo.usesArtifactClass()) {
                    for (final String artifactClass : this.getArtifactClasses()) {
                        combo.setArtifactClass(artifactClass);
                        list.add(combo.clone());
                    }
                    found = true;
                }
                if (found) {
                    continue;
                }
                list.add(combo.clone());
            }
        }
        return list;
    }

    @Override
    public int fillLevel1Statement(final PreparedStatement ps) throws SQLException {
        ps.clearParameters();
        int nextPos = 1;
        ps.setString(nextPos, this.getItemClass());
        ++nextPos;
        if (this.usesItemRarity()) {
            ps.setString(nextPos, this.getItemRarity());
            ++nextPos;
        }
        if (this.usesArmorClass()) {
            ps.setString(nextPos, this.getArmorClass());
            ++nextPos;
        }
        if (this.usesArtifactClass()) {
            ps.setString(nextPos, this.getArtifactClass());
            ++nextPos;
        }
        if (this.usesItemName()) {
            ps.setString(nextPos, this.getItemName().toUpperCase(GDMsgFormatter.locale));
            ++nextPos;
        }
        if (this.usesBonusSkill()) {
            ps.setString(nextPos, this.getBonusSkillID());
            ++nextPos;
        }
        if (this.usesMasteryBonusSkills()) {
            ps.setString(nextPos, this.getBonusSkillID());
            ++nextPos;
        }
        if (this.usesSkillModifier()) {
            ps.setString(nextPos, this.getModifiedSkillID());
            ++nextPos;
        }
        if (this.usesMasteryModifySkills()) {
            ps.setString(nextPos, this.getModifiedSkillID());
            ++nextPos;
        }
        if (this.usesItemSkill()) {
            ps.setString(nextPos, this.getItemSkillID());
            ++nextPos;
        }
        if (this.getMinLevel() != -1) {
            ps.setInt(nextPos, this.getMinLevel());
            ++nextPos;
        }
        if (this.getMaxLevel() != -1) {
            ps.setInt(nextPos, this.getMaxLevel());
            ++nextPos;
        }
        if (this.getMaxCunning() != -1) {
            ps.setInt(nextPos, this.getMaxCunning());
            ++nextPos;
        }
        if (this.getMaxPhysique() != -1) {
            ps.setInt(nextPos, this.getMaxPhysique());
            ++nextPos;
        }
        if (this.getMaxSpirit() != -1) {
            ps.setInt(nextPos, this.getMaxSpirit());
            ++nextPos;
        }
        if (this.usesConversionFrom()) {
            if (this.usesConversionTo()) {
                ps.setString(nextPos, this.getDamageConvertedFrom());
                ++nextPos;
                ps.setString(nextPos, this.getDamageConvertedTo());
                ++nextPos;
                ps.setString(nextPos, this.getDamageConvertedFrom());
                ++nextPos;
                ps.setString(nextPos, this.getDamageConvertedTo());
                ++nextPos;
            } else {
                ps.setString(nextPos, this.getDamageConvertedFrom());
                ++nextPos;
                ps.setString(nextPos, this.getDamageConvertedFrom());
                ++nextPos;
            }
        } else if (this.usesConversionTo()) {
            ps.setString(nextPos, this.getDamageConvertedTo());
            ++nextPos;
            ps.setString(nextPos, this.getDamageConvertedTo());
            ++nextPos;
        }
        if (this.isNoEnemyOnly()) {
            ps.setBoolean(nextPos, false);
            ++nextPos;
        }
        return nextPos;
    }

    @Override
    public String determineLevel1Parameters() {
        String param = this.getItemClass();
        if (this.usesItemRarity()) {
            param = param + ", " + this.getItemRarity();
        }
        if (this.usesArmorClass()) {
            param = param + ", " + this.getArmorClass();
        }
        if (this.usesArtifactClass()) {
            param = param + ", " + this.getArtifactClass();
        }
        if (this.usesItemName()) {
            param = param + ", " + this.getItemName();
        }
        if (this.usesBonusSkill()) {
            param = param + ", " + this.getBonusSkillID();
        }
        if (this.usesSkillModifier()) {
            param = param + ", " + this.getModifiedSkillID();
        }
        if (this.usesItemSkill()) {
            param = param + ", " + this.getItemSkillID();
        }
        if (this.getMinLevel() != -1) {
            param = param + ", " + Integer.toString(this.getMinLevel());
        }
        if (this.getMaxLevel() != -1) {
            param = param + ", " + Integer.toString(this.getMaxLevel());
        }
        if (this.getMaxCunning() != -1) {
            param = param + ", " + Integer.toString(this.getMaxCunning());
        }
        if (this.getMaxPhysique() != -1) {
            param = param + ", " + Integer.toString(this.getMaxPhysique());
        }
        if (this.getMaxSpirit() != -1) {
            param = param + ", " + Integer.toString(this.getMaxSpirit());
        }
        if (this.isNoEnemyOnly()) {
            param += "false";
        }
        return param;
    }

    @Override
    public String determineLevel2Statement(final String level1command, final SelectionCriteria.StatInfo info) {
        String level2command = level1command;
        if (info != null) {
            level2command += " AND (IST.STAT_TYPE = ?";
            if (info.flat == info.percentage) {
                if (info.maxResist) {
                    if (info.flat) {
                        level2command += " AND ((IST.STAT_MIN > 0) OR (IST.MODIFIER > 0) OR (IST.MAX_RESIST > 0))";
                    } else {
                        level2command += " AND (IST.MAX_RESIST > 0)";
                    }
                } else {
                    level2command += " AND ((IST.STAT_MIN > 0) OR (IST.MODIFIER > 0))";
                }
            } else {
                if (info.flat) {
                    level2command += " AND ((IST.STAT_MIN > 0)";
                }
                if (info.percentage) {
                    level2command += " AND ((IST.MODIFIER > 0)";
                }
                if (info.maxResist) {
                    level2command += " OR (IST.MAX_RESIST > 0))";
                } else {
                    level2command += ")";
                }
            }
            level2command += ")";
        }
        return level2command;
    }

    @Override
    public int fillLevel2Statement(final PreparedStatement ps, final String statType, int nextPos) throws SQLException {
        if (statType != null) {
            ps.setString(nextPos, statType);
            ++nextPos;
        }
        return nextPos;
    }

    @Override
    public void addSingleIntCombo(final List<Integer> listAll, final PreparedStatement ps, final String command, final String statType) throws SQLException, UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    @Override
    public void addSingleStringCombo(final List<String> listAll, final PreparedStatement ps, final String command, final String statType) throws SQLException, UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    public void setSuffixID(final String suffixID) {
        this.suffixID = suffixID;
        if (suffixID != null && suffixID.isEmpty()) {
            this.suffixID = null;
        }
    }

    @Override
    public String determineLevel1Statement(final Soulbound soulbound, final SC_HC schc, final boolean isHardcore, final String charName) {
        String command = "SELECT I.ITEM_ID FROM GD_ITEM I";
        final boolean statFilled = !this.getCriteria().statInfos.isEmpty();
        if (this.getCriteria().isSkillBonusUsed()) {
            command = command + ", " + "GD_ITEM_SKILLS" + " ISB, " + "GD_ITEM_SKILL_LEVEL" + " ISBL";
        }
        if (this.getCriteria().isSkillModifierUsed()) {
            command = command + ", " + "GD_ITEM_SKILLMODIFIER" + " ISM";
        }
        if (statFilled) {
            command = command + ", " + "GD_ITEM_STAT" + " IST";
        }
        command += " WHERE ";
        if (this.getCriteria().isSkillBonusUsed()) {
            command += "I.ITEM_ID = ISB.ITEM_ID AND I.ITEM_ID = ISBL.ITEM_ID AND ISB.TYPE = ISBL.TYPE AND ISB.INDEX = ISBL.INDEX AND ";
        }
        if (this.getCriteria().isSkillModifierUsed()) {
            command += "I.ITEM_ID = ISM.ITEM_ID AND ";
        }
        if (statFilled) {
            command += "I.ITEM_ID = IST.ITEM_ID AND ";
        }
        command += "I.ITEM_CLASS = ?";
        if (this.usesItemRarity()) {
            command += " AND I.RARITY = ?";
        }
        if (this.usesArmorClass()) {
            command += " AND I.ARMOR_CLASS = ?";
        }
        if (this.usesArtifactClass()) {
            command += " AND I.ARTIFACT_CLASS = ?";
        }
        if (this.usesItemName()) {
            command += " AND UPPER(I.NAME_FULL) LIKE ?";
        }
        if (this.usesSetItem()) {
            command += " AND I.SET_ID IS NOT NULL";
        }
        if (this.usesBonusSkill()) {
            command += " AND ISB.BONUS_ENTITY = ? AND ISBL.BONUS_VALUE > 0";
        }
        if (this.usesMasteryBonusSkills()) {
            command += " AND ISB.MASTERY_ID = ? AND ISBL.BONUS_VALUE > 0";
        }
        if (this.usesAllSkills()) {
            command += " AND I.PLUS_ALLSKILLS > 0";
        }
        if (this.usesSkillModifier()) {
            command += " AND ISM.SKILL_ID = ?";
        }
        if (this.usesMasteryModifySkills()) {
            command += " AND ISM.MASTERY_ID = ?";
        }
        if (this.usesAllItemSkills()) {
            command += " AND I.ITEM_SKILL_ID IS NOT NULL";
        }
        if (this.usesItemSkill()) {
            command += " AND I.ITEM_SKILL_ID = ?";
        }
        if (this.getMinLevel() != -1) {
            command += " AND I.REQ_LEVEL >= ?";
        }
        if (this.getMaxLevel() != -1) {
            command += " AND I.REQ_LEVEL <= ?";
        }
        if (this.getMaxCunning() != -1) {
            command += " AND I.REQ_DEX <= ?";
        }
        if (this.getMaxPhysique() != -1) {
            command += " AND I.REQ_STR <= ?";
        }
        if (this.getMaxSpirit() != -1) {
            command += " AND I.REQ_INT <= ?";
        }
        if (this.usesPetBonus()) {
            command += " AND I.PET_BONUS_SKILL_ID IS NOT NULL";
        }
        if (this.usesConversionFrom()) {
            if (this.usesConversionTo()) {
                command += " AND (( I.CONVERT_IN = ? AND I.CONVERT_OUT = ? ) OR ( I.CONVERT_IN_2 = ? AND I.CONVERT_OUT_2 = ? ))";
            } else {
                command += " AND (( I.CONVERT_IN = ? ) OR ( I.CONVERT_IN_2 = ? ))";
            }
        } else if (this.usesConversionTo()) {
            command += " AND (( I.CONVERT_OUT = ? ) OR ( I.CONVERT_OUT_2 = ? ))";
        }
        if (this.isNoEnemyOnly()) {
            command += " AND I.ENEMY_ONLY = ?";
        }
        command += this.determineSlotConditions("I.");
        return command;
    }
}
